home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
dbwrend
/
source
/
hit.c
< prev
next >
Wrap
Text File
|
1989-04-17
|
11KB
|
387 lines
/************************************************************************
* *
* Copyright (c) 1987, David B. Wecker *
* All Rights Reserved *
* *
* This file is part of DBW_Render *
* *
* DBW_Render is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY. No author or distributor accepts *
* responsibility to anyone for the consequences of using it or for *
* whether it serves any particular purpose or works at all, unless *
* he says so in writing. Refer to the DBW_Render General Public *
* License for full details. *
* *
* Everyone is granted permission to copy, modify and redistribute *
* DBW_Render, but only under the conditions described in the *
* DBW_Render General Public License. A copy of this license is *
* supposed to have been given to you along with DBW_Render so you *
* can know your rights and responsibilities. It should be in a file *
* named COPYING. Among other things, the copyright notice and this *
* notice must be preserved on all copies. *
************************************************************************
* *
* Authors: *
* DBW - David B. Wecker *
* *
* Versions: *
* V1.0 870125 DBW - First released version *
* *
************************************************************************/
#define MODULE_HIT
#include "ray.h"
void findnormal(np,p,n)
node *np;
vector p,
n;
{
vector ripple,fuzzy,bevelx,bevely,bevelz,tmp;
float t;
int w,j,it;
switch (np->kind)
{
case SPHERE :
SPHERENORMAL(sptr(np)->center,p,n);
break;
case TRIANGLE :
PLANENORMAL(tptr(np)->ve,tptr(np)->vp,n);
break;
case QUAD :
PLANENORMAL(qptr(np)->ve,qptr(np)->vp,n);
break;
case RING :
PLANENORMAL(rptr(np)->ve,rptr(np)->vp,n);
break;
}
if (np->attr.tex != 0)
{ /* don't bother checking if there's no texture */
if (np->attr.tex == 4)
{ /* fiddle with normal for all ripples */
for (w = 0; w < numwaves; w++)
{
calcripple(p,w,ripple); /* calculate the wave perturbation */
vecsum(ripple,n,n); /* add ripple bend to normal */
}
normalize(n); /* make sure it's a unit vector after all that */
}
/* fiddle with normal for one ripple */
else if (np->attr.tex >= 10 && np->attr.tex <= 19)
{
calcripple(p,np->attr.tex - 10,ripple); /* calc wave perturbation */
vecsum(ripple,n,n); /* add ripple bend to normal */
normalize(n); /* make sure it's still a unit vector */
}
/* check for rough pebbly surface */
else if (np->attr.tex >= 90 && np->attr.tex <= 99)
{
j = np->attr.tex - 90; /* select the desired pebble finish */
vecscale(pebble[j].zoom,p,tmp);
fuzzy[0] = turbulence(tmp);
vecscale(1.5,tmp,tmp);
fuzzy[1] = turbulence(tmp);
vecscale(1.5,tmp,tmp);
fuzzy[2] = turbulence(tmp);
if (fuzzy[0] > 0.7)
fuzzy[0] = 0.7;
if (fuzzy[1] > 0.7)
fuzzy[1] = 0.7;
if (fuzzy[2] > 0.7)
fuzzy[2] = 0.7;
if (rnd() < 0.5)
fuzzy[0] = -fuzzy[0];
if (rnd() < 0.5)
fuzzy[1] = -fuzzy[1];
if (rnd() < 0.5)
fuzzy[2] = -fuzzy[2];
vecscale(pebble[j].scale,fuzzy,fuzzy);
vecsum(n,fuzzy,n);
normalize(n);
}
}
/*---------------------------------------------------------------------*/
/* Add any general normal perturbations */
if (np->attr.fuz > 0.0)
{
/* Perturb the normal randomly to produce fuzzy surfaces */
fuzzy[0] = rnd(); /* 0..1 */
fuzzy[1] = rnd();
fuzzy[2] = rnd();
if (rnd() < 0.5)
fuzzy[0] = -fuzzy[0];
if (rnd() < 0.5)
fuzzy[1] = -fuzzy[1];
if (rnd() < 0.5)
fuzzy[2] = -fuzzy[2];
/* 'fuzzy' is now approximately a random unit vector */
vecscale(rnd() * np->attr.fuz,fuzzy,fuzzy);
vecsum(fuzzy,n,n); /* vector addition of fuzz compunent to true normal */
normalize(n); /* Make sure it's still a unit vector */
}
}
int hitcylinder(cp,eye,d,p,t)
cylinder *cp; /* the cylinder */
vector eye; /* source ray origin */
vector d; /* source ray */
vector p;
float *t;
{
float aa,bb,cc,radical,a2,b2,c2,dist1,dist2;
vector otop,oeye,p1,p2,opoint1,opoint2;
/*
* translate bottom of cylinder to 0,0,0
* get translated eyepoint and cylinder top
*/
VECSUB(eye, cp->bottom, oeye);
VECSUB(cp->top,cp->bottom, otop); /* ? */
a2 = cp->a*cp->a;
b2 = cp->b*cp->b;
c2 = cp->c*cp->c;
if (a2 < SMALL) return( FALSE );
if (b2 < SMALL) return( FALSE );
if (c2 < SMALL) return( FALSE );
aa = d[0]*d[0] / a2;
aa += d[2]*d[2] / b2;
aa -= d[1]*d[1] / c2;
bb = d[0]*oeye[0] / a2;
bb += d[2]*oeye[2] / b2;
bb -= d[1]*oeye[1] / c2;
cc = oeye[0]*oeye[0] / a2;
cc += oeye[2]*oeye[2] / b2;
cc -= oeye[1]*oeye[1] / c2;
/*
* descriminate < 0, ray misses cylinder
* descriminate == 0, ray grazes cylinder
*/
if ((radical = (bb*bb) - (4.0*aa*cc)) < 0.0)
return( FALSE );
radical = sqrt(radical);
aa = 2.0 * aa;
if ( aa < SMALL )
return( FALSE );
/* the roots of the quadratic */
dist1 = (-bb + radical) / aa;
dist2 = (-bb - radical) / aa;
VECSCALE(dist1,d,p1);
VECSUM(p1,oeye,p1);
VECSCALE(dist2,d,p2);
VECSUM(p2,oeye,p2);
VECSUB(oeye,p1,opoint1);
VECSUB(oeye,p2,opoint2);
dist1 = NORM(opoint1);
dist2 = NORM(opoint2);
if (dist1 < dist2)
{
VECCOPY(p1,p);
*t = dist1;
}
else
{
VECCOPY(p2,p);
*t = dist2;
}
return( TRUE );
}
int hitsphere(center,radius,eye,d,p,t)
vector center; /* where it is */
vector eye; /* where we are */
vector d;
vector p;
float radius; /* how big it is */
float *t;
{
float r_r,d_r,t2,radical;
vector r;
VECSUB(center,eye,r);
r_r = DOT(r,r);
d_r = DOT(d,r);
if ((radical = (d_r*d_r) + (radius*radius) - r_r) < 0.0)
return( FALSE );
radical = sqrt(radical);
if (d_r < radical)
{
*t = d_r + radical;
t2 = d_r - radical;
}
else
{
*t = d_r - radical;
t2 = d_r + radical;
}
if (fabs(*t) < SMALL)
*t = t2;
if (*t <= 0)
return( FALSE );
VECSCALE((*t),d,p);
VECSUM(p,eye,p);
return( TRUE );
}
int hitplane(p,ve,vp,eye,d,sfs,inter)
vector p,
ve,
vp,
eye,
d,
sfs,
inter;
{
vector h;
float det;
det = ve[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
det -= vp[0] * ((ve[1] * d[2]) - (ve[2] * d[1]));
det += d[0] * ((ve[1] * vp[2])- (ve[2] * vp[1]));
if (det == 0.0)
return FALSE;
vecsub(eye,p,h);
sfs[2] = h[0] * ((ve[1] * vp[2]) - (ve[2] * vp[1]));
sfs[2] -= h[1] * ((ve[0] * vp[2]) - (ve[2] * vp[0]));
sfs[2] += h[2] * ((ve[0] * vp[1]) - (ve[1] * vp[0]));
sfs[2] /= det;
sfs[2] = -sfs[2];
if (sfs[2] < SMALL)
return FALSE;
sfs[0] = h[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
sfs[0] -= h[1] * ((vp[0] * d[2]) - (vp[2] * d[0]));
sfs[0] += h[2] * ((vp[0] * d[1]) - (vp[1] * d[0]));
sfs[0] /= det;
sfs[1] = h[0] * ((ve[2] * d[1]) - (ve[1] * d[2]));
sfs[1] += h[1] * ((ve[0] * d[2]) - (ve[2] * d[0]));
sfs[1] -= h[2] * ((ve[0] * d[1]) - (ve[1] * d[0]));
sfs[1] /= det;
VECCOPY(d,inter);
VECSCALE(sfs[2],inter,inter);
VECSUM(inter,eye,inter);
return TRUE;
}
int hittriangle(tp,eye,d,p,t)
triangle *tp;
vector eye,
d,
p;
float *t;
{
vector sfs;
int hit;
hit = hitplane(tp->position,tp->ve,tp->vp,eye,d,sfs,p) &&
sfs[0] > 0.0 && sfs[1] > 0.0 && sfs[0] + sfs[1] <= 1.0;
*t = sfs[2];
return hit;
}
int hitquad(qp,eye,d,p,t)
quad *qp;
vector eye,
d,
p;
float *t;
{
vector sfs;
int hit = FALSE;
if (hitplane(qp->position,qp->ve,qp->vp,eye,d,sfs,p))
hit = sfs[0] > 0.0 && sfs[1] > 0.0 && sfs[0] <= 1.0 && sfs[1] <= 1.0;
*t = sfs[2];
return hit;
}
int hitring(rp,eye,d,p,t)
ring *rp;
vector eye,
d,
p;
float *t;
{
vector sfs;
float r;
int hit;
hit = hitplane(rp->position,rp->ve,rp->vp,eye,d,sfs,p) &&
(r = sfs[0] * sfs[0] + sfs[1] * sfs[1]) <= rp->maxrad &&
r >= rp->minrad;
*t = sfs[2];
return( hit );
}
void shell(v,v1,v2,n)
float v[];
vector v1[];
node *v2[];
int n;
{
int gap,i,j;
node *temp2;
vector temp1;
float temp;
sorts++; /* Keep statistics */
sort_size += n;
for (gap = n/2; gap > 0; gap /=2)
for (i = gap; i < n; i++)
for (j = i-gap; j>=0 && v[j] > v[j+gap]; j -= gap)
{
temp = v[j];
v[j] = v[j+gap];
v[j+gap] = temp;
VECCOPY(v1[j],temp1);
VECCOPY(v1[j+gap],v1[j]);
VECCOPY(temp1,v1[j+gap]);
temp2 = v2[j];
v2[j] = v2[j+gap];
v2[j+gap] = temp2;
}
}